#! /usr/bin/env python
#coding:utf-8
#written by guolt 2014-02-27 11:00
#version 1.0

import sys
import os
import shutil
import logging
import time
from hashlib import md5
from logging.handlers import SMTPHandler



"""
squid push and purge files!
xxx.status文件状态说明：
1:正在上传；
2:上传完成；
3:正在分发；
4:分发完成；
5:分发失败；

delete文件列表，需要看detele目录；
purge主机对应的ip为内网，对应的主机名和ip写在hosts文件中；

"""

#定义全局变量；
ftp_dir='/usr/local/ftpdata//h3/update/download'
ftp_del_dir='/usr/local/ftpdata//h3/update/download/delete'
cdn_base='/u01/cdnLog'
cdn_log=os.path.join(cdn_base,'check_cdn.log')
cdn_tmp=cdn_base+os.sep+'cdn_tmp'
cdn_host_ip={'idc-cdn1.wuxi.jl':'58.215.80.133','idc-cdn2.wuxi.jl':'58.215.80.134'}
cdn_url="test.grandes.com.cn"

################################
# 创建一个logger
logger = logging.getLogger('check_cdn')
logger.setLevel(logging.DEBUG)

# 创建一个handler，用于写入日志文件
fh = logging.FileHandler(cdn_log)
fh.setLevel(logging.INFO)

# 再创建一个handler，用于输出到控制台
ch = SMTPHandler(mailhost='mail.routon.com',
                                fromaddr='erpadmin@routon.com',
                                toaddrs=['guoletao@routon.com'],
                                subject='check_cdn Warning!',
                                credentials=('erpadmin','erpadmin'),
                                secure=None)
ch.setLevel(logging.WARNING)

# 定义handler的输出格式
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)

# 给logger添加handler
logger.addHandler(fh)
logger.addHandler(ch)

################################


def getStatus(self):
    """
    获得xxx.status文件的tag,然后做出相应的流程处理；
    """
#切换目录；
    os.chdir(ftp_dir)
#tagfile是以xxx.status结尾的文件；
    tagfile=open(self,'r')
    tag=tagfile.readline()
    tag=tag.rstrip('\n')
    tagfile.close()
    return tag      #获得tag值;

def changeStatus(self,status):
    """
    修改文件的状态值.例如：1，2，3，4，5
    """
    status=str(status)
    status_file=open(self,'w')
    status_file.write(status)
    status_file.flush()
    status_file.close()

def getMd5(self):
    """
    获得文件md5值；

    """
    try:
        m = md5()
        a_file = open(self, 'r')
        m.update(a_file.read())
        a_file.close()
        return m.hexdigest()
    except:
        return 123
        logger.info('file: %s have no found!' % self )

def push_file(self,cdn_tmp_dir):
    """
    推送url到各节点；
    """
#    for cdn_host,ip in cdn_host_ip.items():
#        cdn_tmp_dir=cdn_tmp+os.sep+cdn_host
#如果不存在以各节点命名的文件目录，就创建；
#        if not os.path.exists(cdn_tmp_dir):
#            os.mkdir(cdn_tmp_dir)
#如果目录非空就删除，创建空目录；
#        else:
#            if len(os.listdir(cdn_tmp_dir)) != 0:
#                shutil.rmtree(cdn_tmp_dir)
#                os.mkdir(cdn_tmp_dir)

#开始分发url....
    os.chdir(cdn_tmp_dir)
    logger.info("will push URL to cdn node: %s , URL is %s " %(cdn_host,self))
    os.system('wget -q -c -t 5 -T 3 --header "host:%s" http://%s/%s' % (cdn_url,ip,self))

    pushfile_tmp=cdn_tmp_dir+os.sep+self
    md5_pushfile=getMd5(pushfile_tmp)
#        logger.info('hostname:%s ,download file: %s md5 key is : %s' %(cdn_host,pushfile_tmp,md5_pushfile))

    if getMd5(cdn_tmp_dir+os.sep+self) == self.split('.')[0]:
        changeStatus(ftp_push_status,'4')
        logger.info('URL is %s, md5 key is right' %pushfile_tmp)
    else:
        changeStatus(ftp_push_status,'5')
        logger.warning('URL is %s ,md5 key is ERROR,change status to 5.' %pushfile_tmp)

def purge_file(self):
    """
    purge url资源;
    """
    for cdn_host,ip in cdn_host_ip.items():
        purgeFile=self
        print purgeFile
        logger.info("purge URL: %s  at cdn node: %s " %(cdn_host,purgeFile))
        os.system('/usr/sbin/squidclient -h %s -p 80 -m PURGE http://%s/%s' %(cdn_host,cdn_url,purgeFile))



if __name__ == '__main__':
    while True:
#ftp_push_status 为ftp_dir目录下以.status结尾的tag文件(push文件的tag)；ftp_push_file为推送url;
        for ftp_push_file in os.listdir(ftp_dir):
            os.chdir(ftp_dir)
#ftp_push_file要同时是文件，排除目录的类型，并且不是以xxx.status结尾的文件，才符合要求；
            if os.path.isfile(ftp_push_file) and ftp_push_file.endswith('status') == False:
                ftp_push_status=os.path.join(ftp_dir,ftp_push_file.split('.')[0]+'.status')

                if os.path.exists(ftp_push_status) and getStatus(ftp_push_status) == '2':
                    logger.info('URL %s will push to every cdn node.' %ftp_push_file)
#针对一个推送文件，遍历所有主机，进行推送；
                    for cdn_host,ip in cdn_host_ip.items():
                        cdn_tmp_dir=cdn_tmp+os.sep+cdn_host
#如果不存在以各节点命名的文件目录，就创建；
                        if not os.path.exists(cdn_tmp_dir):
                            os.mkdir(cdn_tmp_dir)
#如果目录非空就删除，创建空目录；
                        else:
                            if len(os.listdir(cdn_tmp_dir)) != 0:
                                shutil.rmtree(cdn_tmp_dir)
                                os.mkdir(cdn_tmp_dir)

#将tag置于“正在分发”状态；
                        changeStatus(ftp_push_status,'3')
#开始分发资源
                        push_file(ftp_push_file,cdn_tmp_dir)
                elif os.path.exists(ftp_push_status) and getStatus(ftp_push_status) == '3':
                    changeStatus(ftp_push_status,'3')
#status文件状态为3，执行purge后，在push 该url;
                    logging.info('URL: %s status is pushing,so first purge then push.' % ftp_push_file)
                    purge_file(ftp_push_file)
                    push_file(ftp_push_file,cdn_tmp_dir)
#执行purge后，在push 该url，然后将status文件状态为4，
                    changeStatus(ftp_push_status,'4')


        if os.path.isdir(ftp_del_dir):
            for f_del in os.listdir(ftp_del_dir):
                f_del_ok=os.path.join(ftp_del_dir,f_del.split('.')[0] + '.ok')
#查找目录下有没有f_del对应的f_del_ok文件，没有就代表文件没有purge,如果有，就代表purge完成了.
                if not os.path.exists(f_del.split('.')[0]+'.ok'):
                    purge_file(f_del)
                    logger.info('URL: %s purge success!' %f_del)
                    f_del_ok_create=open(f_del_ok,'w')
                    f_del_ok_create.close()

#        print "@"*30
        time.sleep(10)








